//
// Abstraction of an Autonomous System (AS).
//
// @author Michael Liljenstam, ISTS, Dartmouth College
//
// $Id: AS.java,v 1.4 2003/03/08 01:59:09 mili Exp mili $

package SSF.App.Worm;

import java.util.*;

import com.renesys.raceway.SSF.*;
import cern.jet.random.*;

/**
 *  An (abstract representation of an) Autonomous System.
 */
public class AS {

    /** Ref back to the containing AS graph object. */
    ASGraph myASgraph;

    /** Index in ASGraph array. */
    public int index;
    /** AS number. */
    public int asNumber;
    /** Adjacencies with other ASs. */ 
    public LinkedList adjacencyList;

    /** List of all susceptible hosts in this AS that occur in the network 
     *  level model. */
    public LinkedList susceptibleHostList = null;

    /** List of all border routers in this AS that occur in the network 
     *  level model. */
    public LinkedList borderRouterList = null;

    /** Number of infections that have been triggered in the network level 
     *  model so far. */
    public int triggeredInfections = 0;

    // submodels ...................................................

    /** Worm epidemic state in this AS. */
    public WormEpidemicState  wormModel;
    /** Worm-induced traffic state in this AS. */
    public WormTrafficState   wormTraffic;


    // layout stuff .................................................

    /** True if node has layout information stored. */
    boolean hasLayoutInfo = false;
    /** X coordinate. */
    float   x;
    /** Y coordinate. */
    float   y;

    //....... methods..................................

    public AS(ASGraph asGraph) {
	myASgraph = asGraph;
	adjacencyList = new LinkedList();
	susceptibleHostList = new LinkedList();
	borderRouterList = new LinkedList();
    }

    /** Set index. (My index in ASGraph array.) */
    public void init(int _index) {
	index = _index;
    }

    /** For now: do nothing. */
    public void output() {
	//	wormModel.output();
    }

    /**
     * Signal the network model about new infections in hosts that 
     * are modeled at the network level.
     * Pick hosts at random from the susceptibleHostList in this 
     * AS.
     */
    public void triggerInfections(int numNewInfections) {
	int suscHostsInNetwModel = susceptibleHostList.size();
	int numToInfect = 0;
	if (suscHostsInNetwModel > 0) { // anything left to infect?
	    // pick some at random from network level
	    int suscInAS = (int) Math.floor(wormModel.s);
	    if (suscInAS > 0) { 
		double probInfNetwModel = suscHostsInNetwModel / (double) suscInAS;
		/*     System.err.println("n " + suscHostsInNetwModel + ", p " 
		       + probInfNetwModel + " in AS " + suscInAS); */
		// number of hosts infected in the network model will have 
		// Binomial distribution
		try {
		    MacroscopicModel.ref.infBinomialDistr = 
			new Binomial(suscHostsInNetwModel, probInfNetwModel, 
				     MacroscopicModel.ref.infRNG);
		} catch (java.lang.IllegalArgumentException e) {
		    System.err.println("AS: Bad parameters to Binomial distribution, Bin(" + suscHostsInNetwModel + "," + probInfNetwModel + ")\n");
		    throw e;
		}
		numToInfect = MacroscopicModel.ref.infBinomialDistr.nextInt();
	    }
	    // But if there are more left at network level, then force pick of 
	    // some to make up the difference
	    if (suscInAS < (suscHostsInNetwModel - numToInfect)) { 
		numToInfect += 
		   Math.floor((suscHostsInNetwModel - numToInfect) - suscInAS);
	    }
	
	    for (int i=0; i<numToInfect; i++) {
		int numSusceptibleHosts = susceptibleHostList.size();
		int index = 
		    (int) Math.floor(MacroscopicModel.ref.infUniformDistr.nextDouble() 
					     * numSusceptibleHosts);
		WormProtocolSession h = 
		    (WormProtocolSession) susceptibleHostList.remove(index);
		h.becomeInfected();
		triggeredInfections++;
	    } // for
	} // if anything to infect
    } // triggerInfections()

    /**
     *  Update the scan rate seen by registered border routers at the 
     *  network level.
     */
    public void updateBorderRouters(float scanRatePerRouter) {
	ListIterator it = borderRouterList.listIterator();
	while (it.hasNext()) {
	    GatewayProtocolSession gw = (GatewayProtocolSession) it.next();
	    gw.updateScans(scanRatePerRouter);
	}
    }

    /**
     *  Get number of hosts in this AS that are scanning and whose scans reach 
     *  the outside. Generally this means the number of infected hosts, unless 
     *  gateways are blocking scans, in which case it may be less. 
     *  We make the simplifying assumption that scans will reach the outside 
     *  if <i>any</i> gateway forwards scans.
     */
    public float getNumScanning() {
	boolean scansGoThrough = false;
	ListIterator it = borderRouterList.listIterator();
	while (it.hasNext()) {
	    GatewayProtocolSession gwp = (GatewayProtocolSession) it.next();
	    if (!gwp.scansBlocked) {
		scansGoThrough = true;
	    }
	}
	return scansGoThrough ? wormModel.i : 0F;
    }

    /**
     *  Get fraction of scans from outside that will permeate the gateways and 
     *  reach the inside of the AS. Generally is 1.0 (all scans), unless some 
     *  gateways are blocking scans, in which case it may be less.
     *  We make the simplifying assumption that traffic is perfectly 
     *  load-balanced over the gateways, so each gateway carries or blocks an 
     *  equal fraction of scans.
     */
    public float getScanPermeability() {
	int totGWs = borderRouterList.size(); // # gateways
	// count how many don't block
	int numNotBlocking = 0;
	ListIterator it = borderRouterList.listIterator();
	while (it.hasNext()) {
	    GatewayProtocolSession gwp = (GatewayProtocolSession) it.next();
	    if (!gwp.scansBlocked) {
		numNotBlocking++;
	    }
	}
	return numNotBlocking / (float) totGWs;
    }

    @Override
	public String toString() {
	StringBuffer str = new StringBuffer();
	str.append("AS# " + asNumber + ", index " + index + " -> ");
	ListIterator it = adjacencyList.listIterator();
	while (it.hasNext()) {
	    Integer as = (Integer) it.next();
	    str.append(as.intValue() + ",");
	}
	return str.toString();
    }
} // class AS ....................................................


